package com.vivo.ic.dm;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;

import com.vivo.ic.BaseLib;
import com.vivo.ic.VLog;
import com.vivo.ic.dm.impl.DownloadLifeListener;
import com.vivo.ic.dm.impl.DownloadNetChangeInterface;
import com.vivo.ic.dm.impl.DownloadNotiDealer;
import com.vivo.ic.dm.impl.DownloadNotification;

import java.util.concurrent.CopyOnWriteArrayList;

public class DownloadManager {
    private static final String TAG = Constants.PRE_TAG + "DownloadManager";
    private static DownloadManager sInstance;
    private static Config mConfig;
    
    private DownloadNotification mNotifier;
    private DownloadNotiDealer mNotiDealer;
    private DownloadNetChangeInterface mNetDealer;
    
    private CopyOnWriteArrayList<DownloadLifeListener> mListeners;
    private int mLastNet = 0;
    private ContentResolver mContentResolver = BaseLib.getContext().getContentResolver();
    private HandlerThread mDownloadThread;
    private Handler mDownloadHandler;
    private DownloadReceiver mDownloadReceiver;
    
    /**
     * 私有构造函数，不允许被其他类实例化
     */
    private DownloadManager() {
        mListeners = new CopyOnWriteArrayList<DownloadLifeListener>();
        mLastNet = DMUtil.getNetValueNow();
        mDownloadThread = new HandlerThread("download_queue");
        mDownloadThread.start();
        mDownloadHandler = new Handler(mDownloadThread.getLooper());
        
        mDownloadReceiver = new DownloadReceiver();
        
        BaseLib.getContext().registerReceiver(mDownloadReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
        
        IntentFilter mountedFilter = new IntentFilter();
        mountedFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
        mountedFilter.addDataScheme("file");
        BaseLib.getContext().registerReceiver(mDownloadReceiver, mountedFilter);
        
        VLog.i(TAG, "************* lib_multi_dm version : " + Constants.VERSION + " *************");
    }
    
    /**
     * 获取DownloadManager对象
     */
    public static synchronized DownloadManager getInstance() {
        if (sInstance == null) {
            sInstance = new DownloadManager();
        }
        return sInstance;
    }
    
    /**
     * 初始化自定义参数
     */
    public void init(Config config) {
        if (config == null) {
            config = new Config();
        }
        mConfig = config;
        Constants.PRE_TAG = "ICDM-" + BaseLib.getContext().getPackageName() + "-";
        mNotifier = config.getNotification();
        mNotiDealer = config.getNotiDealer();
        mNetDealer = config.getNetChangeDealer();
        VLog.d(TAG, "DownloadManager init() >>>>>>>>>>>>>>>>>>> ");
    }
    
    /**
     * 是否所有下载都已完成，下载失败的也算完成
     * @return
     */
    public boolean isAllDownloadComplete() {
        Cursor cursor = null;
        try {
            cursor = mContentResolver.query(Downloads.Impl.CONTENT_URI, new String[] { Downloads.Column._ID,
                    Downloads.Column.STATUS}, null, null, null);
            if (cursor != null) {
                for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
//                    long currentId = cursor.getLong(0);
                    int status = cursor.getInt(1);
                    if (!Downloads.Impl.isStatusCompleted(status)) {
                        return false;
                    }
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return true;
    }
    
    /**
     * 设置自定义的通知栏显示
     */
    public void setDownloadNotifier (DownloadNotification notifier) {
        mNotifier = notifier;
    }
    
    /**
     * 设置自定义的通知栏处理程序
     */
    public void setDownloadNotiDealer (DownloadNotiDealer dealer) {
        mNotiDealer = dealer;
    }
    
    /**
     * 设置自定义的网络切换处理
     */
    public void setNetChangeDealer(DownloadNetChangeInterface netDealer) {
        mNetDealer = netDealer;
    }
    
    /**
     * 启动下载核心service入口
     * @param reason 启动service的原因，会在log中被打印
     */
    public static void startDownloadService(Context context, String reason) {
        VLog.i(TAG, "start download service by: " + reason);
        context.startService(new Intent(context, DownloadService.class));
    }
    
    /**
     * 停止下载管理器的DownloadService
     * @param reason 停止service的原因，会在log中被打印
     */
    public void stopDownloadService(String reason) {
        Log.w(TAG, "stopDownloadService for reason " + reason );
        Context context = BaseLib.getContext();
        context.stopService(new Intent(context, DownloadService.class));
            
    }
    
    /**
     * 添加下载过程的listener
     */
    public void addDownloadListener(DownloadLifeListener listener) {
        if (!mListeners.contains(listener)) {
            mListeners.add(listener);
        }
    }
    
    /**
     * 移除下载过程中的listener
     */
    public void removeDownloadListener(DownloadLifeListener listener) {
        mListeners.remove(listener);
    }
    
    /**
     * 清除DM缓存
     */
    public void clear() {
        mListeners.clear();
    }
    
    /**
     * 操作数据库时的序列池
     */
    public Handler getDownloadQuene() {
        return mDownloadHandler;
    }
    
    /**
     * 将暂停下载的请求放入序列池
     */
    public void pauseDownloadInqueue(final String where, final String[] selectionArgs) {
        mDownloadHandler.post(new Runnable() {
            
            @Override
            public void run() {
                pauseDownload(where, selectionArgs);
            }
        });
    }
    
    /**
     * 立即暂停下载
     */
    public void pauseDownload(final String where, final String[] selectionArgs) {
        ContentValues values = new ContentValues();
        values.put(Downloads.Column.STATUS, Downloads.Impl.STATUS_PAUSED_BY_APP);
        values.put(Downloads.Column.CONTROL, Downloads.Impl.CONTROL_PAUSED);
        mContentResolver.update(Downloads.Impl.CONTENT_URI, values, where, selectionArgs);
    }
    
    /**
     * 将继续下载的请求放入序列池
     */
    public void continueDownloadInQueue(final String where, final String[] selectionArgs) {
        mDownloadHandler.post(new Runnable() {
            
            @Override
            public void run() {
                continueDownload(where, selectionArgs);
            }
        });
    }
    
    /**
     * 立即继续下载
     */
    public void continueDownload(final String where, final String[] selectionArgs) {
        ContentValues values = new ContentValues();
        values.put(Downloads.Column.STATUS, Downloads.Impl.STATUS_RUNNING);
        values.put(Downloads.Column.CONTROL, Downloads.Impl.CONTROL_RUN);
        mContentResolver.update(Downloads.Impl.CONTENT_URI, values, where, selectionArgs);
    }
    
    /**
     * 将开始下载请求放入序列池
     */
    public void startDownloadInquene(final ContentValues values) {
        mDownloadHandler.post(new Runnable() {
            
            @Override
            public void run() {
                startDownload(values);
            }
        });
    }
    
    /**
     * 立即开始下载
     */
    public void startDownload(final ContentValues values) {
        values.put(Downloads.Column.CONTROL, Downloads.Impl.CONTROL_RUN);
        mContentResolver.insert(Downloads.Impl.CONTENT_URI, values);
    }
    
    /**
     * 将取消下载请求放入序列池
     */
    public void cancelDownloadInQueue(final String where, final String[] selectionArgs) {
        mDownloadHandler.post(new Runnable() {
            
            @Override
            public void run() {
                cancelDownload(where, selectionArgs);
            }
        });
    }
    
    /**
     * 立即取消下载
     */
    public void cancelDownload(final String where, final String[] selectionArgs) {
        mContentResolver.delete(Downloads.Impl.CONTENT_URI, where, selectionArgs);
    }
    
    /**
     * 获取配置
     * @return
     */
    public static Config getConfig() {
        return mConfig;
    }
    
    // ----------------------包访问权限区域--------------------------
    
    DownloadNetChangeInterface getNetChangeDealer() {
        if (mNetDealer == null) {
            mNetDealer = new DownloadNetChangeDealer(BaseLib.getContext());
        }
        return mNetDealer;
    }
    
    DownloadNotification getNotifier() {
        if (mNotifier == null) {
            VLog.d(TAG, "getNotifier() mNotifier == null");
            mNotifier = new DownloadNotifierEmpty();
        }
        return mNotifier;
    }
    
    DownloadNotiDealer getNotiDealer() {
        if (mNotiDealer == null) {
            mNotiDealer = new DownloadNotiDealerEmpty(); 
        }
        return mNotiDealer;
    }
    
    void setLastNetType(int lastNet) {
        mLastNet = lastNet;
    }
    
    int getLastNetType() {
        return mLastNet;
    }
    
    void notifyDownloadSpeed(final DownloadInfo item, long bytesPerSecond) {
        for (DownloadLifeListener listener : mListeners) {
            try {
                listener.onDownloadSpeedChange(item, bytesPerSecond);
            } catch (Throwable t) {
                VLog.w(TAG, "notifyDownloadSpeed error " + t, t);
            }
        }
    }
    
    void notifyDownloadSize(final DownloadInfo item, long currentSize, long totalSize) {
        for (DownloadLifeListener listener : mListeners) {
            try {
                listener.onDownloadSizeChange(item, currentSize, totalSize);
            } catch (Throwable t) {
                VLog.w(TAG, "notifyDownloadSize error " + t, t);
            }
        }
    }
    
    void notifyDownloadStopped(final DownloadInfo item, final int finalStatus) {
        for (DownloadLifeListener listener : mListeners) {
            try {
                listener.onDownloadStopped(item, finalStatus);
            } catch (Throwable t) {
                VLog.w(TAG, "notifyDownloadComplete error " + t, t);
            }
        }
    }
    
    void notifyDownloadPausedByNetChange(Long[] ids) {
        for (DownloadLifeListener listener : mListeners) {
            try {
                listener.onDownloadPausedByNetChange(ids);
            } catch (Throwable t) {
                VLog.w(TAG, "notifyDownloadComplete error " + t, t);
            }
        }
    }
    
    void notifyDownloadStartByNetChange(Long[] ids) {
        for (DownloadLifeListener listener : mListeners) {
            try {
                listener.onDownloadStartByNetChange(ids);
            } catch (Throwable t) {
                VLog.w(TAG, "notifyDownloadComplete error " + t, t);
            }
        }
    }
}
